package com.tpshion.cloud.common.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.tpshion.cloud.common.support.*;
import org.mindrot.jbcrypt.BCrypt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;

/**
 * jwt工具类
 * 功能：生成token；解密token
 */
public class JwtUtil {

    private static final Logger log = LoggerFactory.getLogger(JwtUtil.class);

    /**
     * 生成token
     * @param authInfo
     * @return
     */
    public static String createToken(AuthInfo authInfo){
        Algorithm algorithm = Algorithm.HMAC256(Constants.SECRET_KEY);
        String token = JWT.create()
                .withIssuer(Constants.ISSUER)
                .withIssuedAt(new Date())
                .withClaim(Field.AUTH_INF, JsonUtil.obj2String(authInfo))
                .sign(algorithm);
        return token;
    }

    /**
     * 检查token
     * @param token
     */
    public static void checkToken(String token){
        try {
            Algorithm algorithm = Algorithm.HMAC256(Constants.SECRET_KEY);
            JWTVerifier jwtVerifier = JWT.require(algorithm).withIssuer(Constants.ISSUER).build();
            jwtVerifier.verify(token);
        }catch (Exception e){
            throw new CoreException(ErrorCode.TOKEN_ERROR);
        }
    }

    /**
     * 从token中获取验证信息
     * @param token
     * @return
     */
    public static AuthInfo getUserInfo(String token){
        DecodedJWT decode = JWT.decode(token);
        AuthInfo authInfo = JsonUtil.string2Obj(decode.getClaim(Field.AUTH_INF).asString(), AuthInfo.class);
        return authInfo;
    }

    /**
     * 获取token过期时间
     * @param token
     * @return
     */
    public static Date getExpTime(String token){
        DecodedJWT decode = JWT.decode(token);
        Date exp = decode.getClaim("exp").asDate();
        return exp;
    }

    /**
     * 使用BCrypt进行加密
     * @param password
     * @return
     */
    public static String hashpw(String password){
        return BCrypt.hashpw(password,BCrypt.gensalt());
    }

    /**
     * 使用BCrypt进行密码校验
     * @param plaintext
     * @param hashed
     * @return
     */
    public static Boolean checkpw(String plaintext, String hashed){
        return BCrypt.checkpw(plaintext, hashed);
    }

    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        AuthInfo authInfo = new AuthInfo("userId");
        String token = createToken(authInfo);
        System.out.println(token);
        AuthInfo userInfo = getUserInfo(token);
        System.out.println(userInfo);
        Date expTime = getExpTime(token);
        System.out.println(expTime);
    }

}
